/*
 * Floor.cpp
 *
 *  Created on: 15/04/2013
 *      Author: juan
 */
#include "Floor.h"

#include "../exceptions/ArgumentInvalidError.h"
#include <vector>
#include <cmath>
#define VERTICESDEPISO 30
#define VERTICEDECIERREEXT 17
#define ALTURA_FLOOR (0.25)

using namespace std;

void Floor::create_vertex_buffer(GLuint program) {

	cubos = new list<Cube*>();
	Cube* auxiliar = new Cube(program);
	//auxiliar->load_texture("brick.jpg");
	auxiliar->traslate(glm::vec3(-2.0, 0.0, 0.0));
	auxiliar->scale(glm::vec3(8.0, 6.0, 2 * ALTURA_FLOOR));
	cubos->push_back(auxiliar);
	auxiliar = new Cube(program);
	//auxiliar->load_texture("brick.jpg");
	auxiliar->traslate(glm::vec3(5.5, 2.5, 0.0));
	auxiliar->scale(glm::vec3(7.0, 1.0, 2 * ALTURA_FLOOR));
	cubos->push_back(auxiliar);
	auxiliar = new Cube(program);
	//auxiliar->load_texture("brick.jpg");
	auxiliar->traslate(glm::vec3(5.5, -1.5, 0.0));
	auxiliar->scale(glm::vec3(7.0, 1.0, 2 * ALTURA_FLOOR));
	cubos->push_back(auxiliar);
	auxiliar = new Cube(program);
	//auxiliar->load_texture("brick.jpg");
	auxiliar->traslate(glm::vec3(8.25, 0.5, 0.0));
	auxiliar->scale(glm::vec3(1.5, 3.0, 2 * ALTURA_FLOOR));
	cubos->push_back(auxiliar);

	std::vector<DatosVertice> texturas;
	DatosVertice datos;
	datos.texture = glm::vec2(0.0, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(0.0, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(1.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(1.0 / 6, 0.0);
	texturas.push_back(datos);

	datos.texture = glm::vec2(1.0 / 6, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(1.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(2.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(2.0 / 6, 0.0);
	texturas.push_back(datos);

	datos.texture = glm::vec2(2.0 / 6, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(2.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(0.5, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(0.5, 0.0);
	texturas.push_back(datos);

	datos.texture = glm::vec2(0.5, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(0.5, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(4.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(4.0 / 6, 0.0);
	texturas.push_back(datos);

	datos.texture = glm::vec2(4.0 / 6, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(4.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(5.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(5.0 / 6, 0.0);
	texturas.push_back(datos);

	datos.texture = glm::vec2(5.0 / 6, 0.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(5.0 / 6, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(1.0, 1.0);
	texturas.push_back(datos);
	datos.texture = glm::vec2(1.0, 0.0);
	texturas.push_back(datos);

	for (std::list<Cube*>::iterator it = cubos->begin(); it != cubos->end(); it++) {
		Cube* aux = (*it);
		aux->change_texture_data(texturas);
	}

}

void Floor::create_index_buffer() {
	/*index_buffer_size = 24;
	 index_buffer = new GLuint[index_buffer_size];
	 GLuint index_buffer_aux[] = {0,1,5,6,7,2,4,9,3,8,1,2,11,12,16,17,18,13,15,20,14,19,12,13};
	 memcpy(index_buffer, index_buffer_aux, index_buffer_size+1);
	 index_buffer = index_buffer_aux;*/
}

Floor::Floor(GLuint program) :
		Figure(program) {
	this->create_vertex_buffer(program);
	this->create_index_buffer();
	index_internal_buffer = NULL;
	index_internal_buffer_size = 0;
	normal_external_buffer_size = 0;
	normal_external_buffer = NULL;
	normal_internal_buffer_size = 0;
	normal_internal_buffer = NULL;
}

Floor::~Floor() {
	for (std::list<Cube*>::iterator it = cubos->begin(); it != cubos->end(); it++) {
		Cube* aux = (*it);
		delete aux;
	}
	delete cubos;
}

void Floor::set_texture_id(GLuint id) {
	for (std::list<Cube*>::iterator it = cubos->begin(); it != cubos->end(); it++) {
		Cube* aux = (*it);
		aux->set_texture_id(id);
	}
}

void Floor::draw(GLuint program, glm::mat4 & world_matrix) {
	glm::mat4 matriz = world_matrix * this->model_matrix;

	for (std::list<Cube*>::iterator it = cubos->begin(); it != cubos->end(); it++) {
		Cube* aux = (*it);
		//aux->activate_texture();
		aux->draw(program,world_matrix);
	}

// Bind Normal Matrix
//GLuint location_normal_matrix = glGetUniformLocation(program, "NormalMatrix");
//if (location_normal_matrix >= 0) {
//	glUniformMatrix3fv(location_normal_matrix, 1, GL_FALSE, &normal_matrix[0][0]);
//}

// Bind Model Matrix
	/*GLuint location_world_matrix = glGetUniformLocation(program, "ModelMatrix");
	 if (location_world_matrix >= 0) {
	 glUniformMatrix4fv(location_world_matrix, 1, GL_FALSE, &matriz[0][0]);
	 }

	 glEnableClientState(GL_VERTEX_ARRAY);
	 //glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	 glVertexPointer(3, GL_FLOAT, 0, vertex_buffer);
	 glNormalPointer(GL_FLOAT, 0, normal_buffer);
	 glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, index_buffer);
	 glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_INT, &index_buffer[4]);
	 /*
	 //cierro el exterior
	 glNormalPointer(GL_FLOAT, 0, normal_external_buffer);
	 glDrawElements(GL_TRIANGLE_STRIP, VERTICEDECIERREEXT, GL_UNSIGNED_INT, &index_buffer[30]);

	 //Normales del cierre
	 glNormalPointer(GL_FLOAT, 0, normal_internal_buffer);
	 glDrawElements(GL_TRIANGLE_STRIP, index_internal_buffer_size, GL_UNSIGNED_INT, index_internal_buffer);
	 //glDrawElements(GL_QUADS, index_buffer_size, GL_UNSIGNED_INT, index_buffer);

	 glDisableClientState(GL_VERTEX_ARRAY);
	 //glDisableClientState(GL_TEXTURE_COORD_ARRAY);*/
}
